<template>
  <a-spin :spinning="loading" class="wrapper">
    <div id="vueWangEditor" ref="editor"></div>
    <input v-if="fileShow" style="width: 0px" type="file" id="fileExport" @change="handleFileChange" ref="inputer" />
    <div v-for="(i, index) in fileList" :key="index">
      <a-icon type="paper-clip" />
      {{ i.name }}
      <a-popconfirm title="确定删除吗?" @confirm="() => delFile(i, index)">
        <a-icon type="delete" v-if="!disabled" />
      </a-popconfirm>
    </div>
  </a-spin>
</template>

<script>
// 引入 wangEditor
import E from "wangeditor";
import axios from "axios";

const { PanelMenu } = E;

class AttachMenu extends PanelMenu {
  constructor(editor) {
    const $elem = E.$(
      '<div class="yeditor_attach_menu w-e-menu" data-title="附件"><i class="icon iconfont icon-qita" style="color: #999; font-size: 18px; font-weight: bold"></i></div>'
    );
    super($elem, editor);
  }

  clickHandler() {
    this.editor.config.customUploadFile();
  }
  createPanel() {}
  tryChangeActive() {}
}

export default {
  data() {
    return {
      fileList: [],
      fileShow: false,
      token: this.$store.state.auth.token,
      editor: null,
      isTxt: true,
      loading: false
    };
  },
  props: {
    value: {
      type: String,
      default: ""
    },
    disabled: {
      type: Boolean,
      default: false
    },
    fileListVal: {
      type: Array,
      default: () => []
    },
    menus: {
      type: Array,
      default: null
    }
  },
  watch: {
    fileListVal(val) {
      if (val) {
        this.fileList = val;
      }
    },
    value(a) {
      if (this.isTxt) {
        this.editor.txt.html(a);
        this.isTxt = false;
      }
    }
  },
  mounted() {
    const _this = this;
    const editor = new E(`#vueWangEditor`);
    editor.menus.extend("appendix", AttachMenu);
    // 配置 onchange 回调函数，将数据同步到 vue 中
    editor.config.onchange = (newHtml) => {
      this.$emit("change", newHtml, editor.txt.text());
      this.$emit("input", newHtml, editor.txt.text());
      // this.value = newHtml;
    };
    editor.config.customUploadFile = () => {
      this.fileShow = true;
      this.$nextTick(() => {
        this.$refs.inputer.click();
      });
    };
    editor.config.uploadImgShowBase64 = false;
    editor.config.showLinkImg = false;
    editor.config.height = 500;
    editor.config.customUploadImg = function (resultFiles, insertImgFn) {
      var params = new FormData();
      params.append("files", resultFiles[0]);
      _this.loading = true;
      axios({
        url: `/file/api/v1/general/uploadImg`,
        method: "post",
        data: params
      })
        .then((success) => {
          insertImgFn(success.data.data[0]);
          _this.loading = false;
        })
        .catch(() => {
          _this.loading = false;
        });
    };

    editor.config.pasteTextHandle = (pasteStr) => {
      const containsImage = pasteStr.search(/<img /i) >= 0;
      if (containsImage) {
        this.loading = true;
        this.disposePasteImg(pasteStr)
          .then((res) => {
            this.editor.txt.append(res);
            this.loading = false;
          })
          .catch(() => {
            this.loading = false;
          });
      }
      return containsImage ? "" : pasteStr;
    };
    // 配置全屏功能按钮是否展示
    editor.config.showFullScreen = false;
    // 创建编辑器
    // / 默认情况下，显示所有菜单
    editor.config.menus = this.menus || [
      "head", // 标题
      "bold", // 粗体
      "fontSize", // 字号
      "lineHeight", // 缩进
      "fontName", // 字体
      "italic", // 斜体
      "underline", // 下划线
      "strikeThrough", // 删除线
      "foreColor", // 文字颜色
      "backColor", // 背景颜色
      "justify", // 对齐方式
      "undo", // 撤销
      "redo", // 重复
      "list", // 列表
      "link", // 插入链接
      "quote", // 引用
      "table", // 表格
      "image", // 插入图片
      "splitLine", // 分割线
      "appendix" // 附件
    ];

    editor.create();
    this.editor = editor;
    this.editor.txt.html(this.value); // 重新设置编辑器内容
    if (this.disabled) {
      this.editor.$textElem.attr("contenteditable", false);
    } else {
      this.editor.$textElem.attr("contenteditable", true);
    }
  },
  beforeDestroy() {
    this.editor = null;
  },
  methods: {
    delFile(i, index) {
      this.fileList.splice(index, 1);
      this.$emit("saveFileList", this.fileList);
    },
    handleFileChange() {
      const inputFile = this.$refs.inputer.files[0];
      var params = new FormData();
      params.append("files", inputFile);
      axios({
        url: `/file/api/v1/general/upload/inline`,
        method: "post",
        data: params
      }).then((success) => {
        this.$message.success(`${inputFile.name}上传成功！`);
        this.fileList.push({
          name: inputFile.name,
          url: success.data.data[0]
        });
        this.$emit("saveFileList", this.fileList);
      });
      this.fileShow = false;
    },
    disposePasteImg(pasteStr) {
      const _this = this;
      return new Promise(function (resolve, reject) {
        let imgNum = 0;
        const imgReg = /<img.*?(?:>|\/>)/gi;
        const srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i;
        try {
          pasteStr.replace(imgReg, (txt) => {
            return txt.replace(srcReg, (src) => {
              let img_src = src.match(srcReg)[1];
              img_src = img_src.replace(/\?.*/i, "");
              imgNum++;

              _this
                .imgUrlSwitchBlob(img_src)
                .then((res) => {
                  pasteStr = pasteStr.replace(img_src, res);
                  imgNum--;
                  if (imgNum === 0) {
                    resolve(pasteStr);
                  }
                })
                .catch((err) => {
                  reject(err);
                });
            });
          });
        } catch (err) {
          reject(err);
        }
      });
    },
    imgUrlSwitchBlob(param) {
      return new Promise((resolve, reject) => {
        try {
          const suffix = param.substring(param.lastIndexOf(".") + 1);
          const key = new Date().getTime() + Math.random().toString().substr(2, 5) + "." + suffix;
          const image = new Image();
          image.setAttribute("crossOrigin", "anonymous");
          image.src = param;
          image.onload = () => {
            const canvas = document.createElement("canvas");
            canvas.width = image.width;
            canvas.height = image.height;
            const ctx = canvas.getContext("2d");
            ctx.drawImage(image, 0, 0, image.width, image.height);
            canvas.toBlob((blob) => {
              this.uploadPasteImg(key, blob).then((res) => {
                resolve(res);
              });
            });
          };
        } catch (err) {
          reject(err);
        }
      });
    },
    uploadPasteImg(key, file) {
      const data = new FormData();
      data.append("files", file, key);
      return new Promise((resolve, reject) => {
        axios({
          url: `/file/api/v1/general/upload/inline`,
          method: "post",
          data
        })
          .then((res) => {
            resolve(res.data.data[0]);
          })
          .catch((err) => {
            reject(err);
          });
      });
    }
  }
};
</script>

<style lang="scss" scoped>
.wrapper {
  width: 1200px;
  margin: 0 auto;
  position: relative;
}
::v-deep img {
  max-width: 100%;
}
</style>
